home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Messaging / OSL / OSLClAcc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  14.0 KB  |  491 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        OSLClAcc.c (Orignal name: OSLCallAccessor.c)
  3.  
  4.     Contains:    
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <7>     6/28/95    eeh        1262143: dispose swap token
  13.          <6>     5/12/95    NP        1246047: OSL doesn't dispose tokens
  14.                                     correctly when swapping.
  15.          <5>     3/13/95    NP        1226003: Remove GetContainingFrame from the
  16.                                     API. Don't null out user token.
  17.          <4>     2/22/95    eeh        1222904: fix use of SetCurrentContext
  18.          <3>      2/8/95    NP        1218550: Don't allocate OSLContexts
  19.                                     dynamically.
  20.          <2>     8/19/94    NP        1181622: Ownership fix.
  21.         <17>      5/2/94    eeh        bug #1160654: various PPC native changes
  22.         <16>      2/7/94    NP        Tiger Team doings.
  23.         <15>    11/30/93    NP        Added error checking.
  24.         <14>    11/18/93    JA        Made RecursiveCallObjectAccessor static
  25.                                     (prevents missing-prototype error in THINK)
  26.         <13>     11/2/93    NP        Moved back pascal keyword for MPW C.
  27.         <12>     11/2/93    NP        Move pascal keyword.
  28.         <11>    10/28/93    NP        Fixed bug where switching contexts could
  29.                                     only be done once. Is now a recursive
  30.                                     routine.
  31.         <10>    10/22/93    NP        Removed obsolete context parameter from
  32.                                     some functions.
  33.          <9>    10/18/93    NP        Added #pragma unused statements.
  34.          <8>    10/11/93    NP        Added DebugStr.
  35.          <7>     9/10/93    NP        Fixed some bugs.
  36.          <6>      9/3/93    NP        Use "switch" constant instead of
  37.                                     hard-coded.
  38.          <5>     8/18/93    NP        Implemented for new context scheme.
  39.          <4>     8/16/93    NP        Adjusted for latest OSL proposal.
  40.          <3>     7/28/93    NP        Mods for new token type, OSLToken.
  41.          <2>     7/21/93    NP        Fixed #includes.
  42.          <1>     7/21/93    NP        first checked in
  43.  
  44.     To Do:
  45. */
  46.  
  47. /*                                            
  48.     ©Apple Computer, Inc.  1992         
  49.           All Rights Reserved.                
  50.     Author: Eric House
  51.                                             */
  52. #include <Errors.h>
  53.  
  54. #ifndef _OSLPRIV_
  55. #include "OSLPriv.h"
  56. #endif
  57.  
  58. #ifndef _CNTXTOSL_
  59. #include "CntxtOSL.h"
  60. #endif
  61.  
  62. #ifndef _OSLTOKEN_
  63. #include "OSLToken.h"
  64. #endif
  65.  
  66. #pragma segment AEObjSuppt
  67.  
  68. pascal OSErr 
  69. iAERemoveObjectAccessor(    DescType        desiredClass ,
  70.                             DescType        containerType ,
  71.                             OSLAccessorUPP    handler ,
  72.                             Boolean            isSysHandler);
  73.  
  74.  
  75. // GetTableInfo()
  76. // find the handler and refcon for the corresponding key, wildcard is used
  77. // This is lifted directly from Ed's AEHandlerTable.inc1.p
  78. // NOTE: <eeh> this duplicates a function in the AEM.  When we fold this into AEM
  79. // we need to take it out.
  80.  
  81. static Boolean
  82. GetTableInfo(     HHand theTable ,                 //--> handle to table
  83.                   OSType key1, OSType key2 ,     // --> search these keys
  84.                 ObjectAccessorValue* theHandlerRec )  // <-- return this ProcPtr record }
  85. {
  86.     ObjectAccessorKey theKeyRec ;
  87.  
  88.     Boolean result = true ;
  89.     theKeyRec.firstKey = key1;
  90.     theKeyRec.secondKey = key2;
  91.  
  92.     if ( AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec,
  93.             (HEntryPtr)theHandlerRec ) != noErr )
  94.     {
  95.         theKeyRec.firstKey = typeWildCard ;
  96.         if ( AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec, 
  97.             (HEntryPtr)theHandlerRec) != noErr )
  98.         {
  99.             theKeyRec.firstKey = key1;
  100.             theKeyRec.secondKey = typeWildCard;
  101.             if ( AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec, 
  102.                     (HEntryPtr)theHandlerRec) != noErr )
  103.             {
  104.                 theKeyRec.firstKey = typeWildCard;
  105.                 result = AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec, 
  106.                     (HEntryPtr)theHandlerRec) == noErr ;
  107.             }
  108.         }
  109.     }
  110.     return result ;
  111. }
  112.  
  113. // Recursively build a new range descriptor whose ccnt containers have been
  114. // replaced by the token container
  115.  
  116. static OSErr
  117. DoSubst( AEDesc *theObj, ContainedTokenRecord *tokenRec,
  118.         DescType containerClass, OSLToken dContainerToken ) //recurse until reach bottom }
  119. {
  120.     AERecord dObjRecord ;
  121.     AEDesc dTheContainer ;
  122.     OSErr err;
  123.  
  124.     if ( theObj->descriptorType == typeObjectSpecifier )    
  125.     {
  126.         err = AECoerceDesc( theObj, typeAERecord, &dObjRecord ) ;
  127.         IgnoreOSErr( AEDisposeDesc( theObj ) ) ;
  128.         if ( err != noErr ) goto L100 ;
  129.  
  130.         err = AEGetKeyDesc( &dObjRecord, keyAEContainer, typeWildCard,
  131.                 &dTheContainer ) ;
  132.         if ( err != noErr ) goto L200 ;
  133.  
  134.         err = DoSubst( &dTheContainer, tokenRec, containerClass,
  135.                 dContainerToken ) ;
  136.         if ( err != noErr ) goto L200 ;
  137.  
  138.         err = AEPutKeyDesc( &dObjRecord, keyAEContainer, &dTheContainer ) ;
  139.         if ( err != noErr ) goto L300 ;
  140.  
  141.         err = AECoerceDesc( &dObjRecord, typeObjectSpecifier, theObj ) ;
  142.  
  143. L300:
  144.         IgnoreOSErr( AEDisposeDesc( &dTheContainer ) ) ;
  145. L200:
  146.         IgnoreOSErr( AEDisposeDesc( &dObjRecord ) ) ;
  147.     }
  148.     else if ( theObj->descriptorType == typeCurrentContainer )
  149.     {
  150.         IgnoreOSErr( AEDisposeDesc( theObj ) ) ;
  151.         tokenRec->tokenClass = containerClass ;
  152.         tokenRec->token = dContainerToken ;
  153.         err = AECreateDesc( typeToken, (Ptr)tokenRec, sizeof( *tokenRec ),
  154.             theObj ) ;
  155.     }
  156.     else
  157.         err = noErr ;
  158. L100:
  159.     return err ;
  160. }
  161.  
  162.  
  163. static OSErr
  164. SubstContainerForccnt( OSLToken dContainerToken, DescType containerClass,
  165.     AEDesc *rangeDesc )
  166. {
  167.     AEDesc obj, dRangeRecord ;
  168.     OSErr err ;
  169.     ContainedTokenRecord tokenRec ;
  170.         
  171.  
  172.     err = AECoerceDesc( rangeDesc, typeAERecord, &dRangeRecord ) ;
  173.     if ( err != noErr ) goto L100 ;
  174.  
  175. //        IgnoreOSErr( AEDisposeDesc( rangeSelData ) ) ;        { don't dispose: this is just a local copy }
  176.  
  177.     err = AEGetKeyDesc( &dRangeRecord, keyAERangeStart, typeWildCard, &obj ) ;
  178.     if ( err != noErr ) goto L200 ;
  179.         
  180.     err = DoSubst( &obj, &tokenRec, containerClass, dContainerToken ) ;
  181.     if ( err != noErr ) goto L200 ;
  182.  
  183.     err = AEPutKeyDesc( &dRangeRecord, keyAERangeStart, &obj ) ;
  184.     IgnoreOSErr( AEDisposeDesc( &obj ) ) ;
  185.     if ( err != noErr ) goto L200 ;
  186.  
  187.  
  188.  
  189.     err = AEGetKeyDesc( &dRangeRecord, keyAERangeStop, typeWildCard, &obj ) ;
  190.     if ( err != noErr ) goto L200 ;
  191.  
  192.     err = DoSubst( &obj, &tokenRec, containerClass, dContainerToken ) ;
  193.     if ( err != noErr ) goto L200 ;
  194.  
  195.     err = AEPutKeyDesc( &dRangeRecord, keyAERangeStop, &obj ) ;
  196.     IgnoreOSErr( AEDisposeDesc( &obj ) ) ;
  197.     if ( err != noErr ) goto L200 ;
  198.  
  199.     err = AECoerceDesc( &dRangeRecord, typeRangeDescriptor, rangeDesc ) ;
  200. L200:
  201.     IgnoreOSErr( AEDisposeDesc( &dRangeRecord ) ) ;
  202. L100:
  203.     return err ;
  204. }
  205.  
  206.  
  207.  
  208.     /*———————————————————————— TryAccessor ————————————————————————*/
  209.  
  210. static OSErr
  211. TryAccessor( GlobalRecHandle aGlobalRef, Boolean *iFoundIt,
  212.         OSLToken  container, DescType  wantType, AEDesc selectionData,
  213.         DescType  containerClass, DescType form, OSLToken *value ) 
  214. {
  215.     OSErr                 err ;
  216.     ObjectAccessorValue theValue ;
  217.  
  218.     err = errAEEventNotHandled ;
  219.     if ( aGlobalRef != NULL )
  220. //    WITH aGlobalRef** DO
  221.     {
  222.         GlobalRecPointer gp = *aGlobalRef ;
  223.         if ( GetTableInfo( gp->accessorHashTable, wantType,
  224.             container.descriptorType, &theValue ) )
  225.             {
  226.             // <eeh> need to check for NULL if  don't check for NULL
  227.             // when installing
  228.                 err = CallOSLAccessorProc( theValue.handler, wantType,
  229.                         &container, containerClass, form, &selectionData,
  230.                         value, theValue.handlerRefcon ) ;
  231.                 *iFoundIt = true ;
  232.             }
  233.         }
  234.     return err ;
  235. } // TryAccessor
  236.  
  237.     /*———————————————————— RecursiveCallObjectAccessor ——————————————————————*/
  238.  
  239. static
  240. OSErr RecursiveCallObjectAccessor( DescType  wantType , OSLToken  container ,
  241.         DescType  containerClass , DescType form,
  242.          AEDesc selectionData , OSLToken *value, Boolean* iFoundIt,
  243.         OSLContext* curContext )
  244. {
  245.     OSLContext    afterContext;
  246.     OSErr        err = noErr;
  247.  
  248.     err = (*(ObjectAccessorCaller)(*curContext->getCallerProc)
  249.             (kObjectAccessor))
  250.             (wantType, &container, containerClass, form, &selectionData, value,
  251.                 iFoundIt, curContext->refCon);
  252.     // CONTEXT CHANGED?
  253.     if (value->descriptorType == kSwitchDescType && (err == noErr))
  254.     {
  255.         // DISPOSE OLD CONTAINER TOKEN????
  256.         err = OSLGetTokenContext(value, &afterContext);
  257.         if (err)
  258.             return err;
  259.         err = SetCurrentContext(&afterContext);
  260.         if (err)
  261.             return err;
  262.  
  263.         // this will leak if not disposed now; it's done its job.
  264.         iAEDisposeToken( value );
  265.  
  266.         // DISPOSE TOKEN???? PROBABLY.
  267.         containerClass = typeNull;
  268. //        THIS LINE BELOW DOESN'T SEEM TO WORK. THE DESCRIPTOR WILL GET DISPOSED
  269. //        TWICE. ONCE HERE AND ONCE IN INTERNALRESOLVE (LOOK FOR DISPOSAL OF
  270. //        dContainerToken.)
  271. //        iAEDisposeToken(&container);
  272.         MakeNullToken(&container);
  273.         err = RecursiveCallObjectAccessor(wantType, container, containerClass,
  274.                                             form, selectionData, value,
  275.                                             iFoundIt, &afterContext);
  276.     }
  277.     return err;
  278. } /* RecursiveCallObjectAccessor */
  279.  
  280.     /*———————————————————————— iCallAccessor ————————————————————————*/
  281.  
  282. pascal OSErr
  283. iCallAccessor( DescType  wantType , OSLToken  container ,
  284.         DescType  containerClass , DescType form,
  285.          AEDesc selectionData , OSLToken *value )
  286. {
  287.  
  288.     OSErr                  err ;
  289.     long                  nElements ;
  290.     OSLContext            curContext;
  291.  
  292.     // 5/13 This guy allows to distinguish between an access||NotFound
  293.     // error and the case where there was an access|| but it returned
  294.     //eventNotHandled (as when it decides it _does_ want me to do whoses). */
  295.  
  296.     Boolean  madeACopy, iFoundIt ;
  297.     
  298.     
  299.     err = noErr ;
  300.     iFoundIt = false ;
  301.     
  302.     // if marking not being used and container is an empty list and we're not
  303.     // looking for kAEAll of something then return error.  If we do want all
  304.     // then just return the empty list. Fixes LLD-???
  305.  
  306.     if ( container.descriptorType == typeAEList )            // type of 'list' assumes not a mark token.  Tell Mitch  
  307.     {
  308.         err = AECountItems( &container, &nElements ) ;
  309.         if ( err != noErr )
  310.         {
  311.             return err ;
  312.         }
  313.         if ( nElements == 0 )
  314.         {
  315.             if ( (form == formAbsolutePosition) 
  316.                     && (selectionData.descriptorType == typeAbsoluteOrdinal)
  317.                     && (**((DescTypeHandle)(selectionData.dataHandle)) == kAEAll) )
  318.             {
  319.                 DebugStr("\pOSLCllAcc.iCallAccessor: Creating list. Call Nick.");
  320.                 err = AECreateList( NULL, 0, false, value ) ;
  321.             }
  322.             else
  323.                 err = errAENoSuchObject ; // was errAEEmptyListContainer: fixes LLD-UPG-??? */
  324.             return err ;
  325.         }
  326.     }
  327.  
  328.     // If this is a range, then create a new range specifier in which any 
  329.     // 'ccnt' descriptors are replaced with the token representing the 
  330.     // actual container.  Do not dispose the previous range specifier.  The
  331.     // new one we create exists only as long as it takes to make this
  332.     // call.  The old one still lives in other data structures, which will
  333.     // need to be allowed to do the disposal
  334.  
  335.     if ( form == formRange )
  336.     {
  337.         FailErr( SubstContainerForccnt( container, containerClass,
  338.             &selectionData ), err, errExit ) ;
  339.         madeACopy = true ;
  340.     }
  341.     else
  342.         madeACopy = false ;
  343.  
  344.      // try the application specific dispatch first
  345. //      err = TryAccessor( GetGlobalRef(), &iFoundIt, container, wantType,
  346. //            selectionData, containerClass, form, value ) ;
  347.  
  348.     err = GetCurrentContext(&curContext);
  349.     if (!err)
  350.         err = RecursiveCallObjectAccessor(wantType, container, containerClass,
  351.                                             form, selectionData, value,
  352.                                             &iFoundIt, &curContext);
  353.  
  354.     if ( err == errAEEventNotHandled )
  355.         err = TryAccessor(GetSysGlobal(), &iFoundIt, container, wantType,
  356.                 selectionData, containerClass, form, value ) ;
  357.     if ( (err == errAEEventNotHandled) && (! iFoundIt) )
  358.         err = errAEAccessorNotFound ;
  359.  
  360.     if ( madeACopy )
  361.         IgnoreOSErr( AEDisposeDesc( &selectionData ) ) ;
  362.  
  363.  
  364. FAIL_ERR_PROC(err,errExit)
  365. END_FAIL_ERR_PROC(err)
  366.     
  367. } /* iCallAccessor */
  368.  
  369. //———————————————————————— iAEGetObjectAccessor ————————————————————————
  370. pascal OSErr
  371. iAEGetObjectAccessor(    DescType            desiredClass,
  372.                         DescType            containerType,
  373.                         OSLAccessorUPP        *handler,
  374.                         long                 *handlerRefcon,
  375.                         Boolean                isSysHandler)
  376.  
  377. {
  378.     ObjectAccessorKey        key ;
  379.     ObjectAccessorValue        theValue ;
  380.     GlobalRecHandle            properGlobal ;
  381.     OSErr                    out;
  382.         
  383.     // NEED TO IMPLEMENT THIS TO CALL THROUGH CONTEXTS
  384.     DebugStr("\pOSLClAcc.iAEGetObjectAccessor: No good. Exit to shell, please.");
  385.  
  386.     out = noErr;
  387.     
  388.     if ( isSysHandler )
  389.         properGlobal = GetSysGlobal() ;
  390.     else
  391.         properGlobal = GetGlobalRef() ;
  392.         
  393.     key.firstKey = desiredClass;
  394.     key.secondKey = containerType;
  395.     
  396.     out = AEGetKeyValue( (*properGlobal)->accessorHashTable,
  397.         NULL, (KeyPtr)&key, (HEntryPtr)&theValue ) ;
  398.  
  399.     if ( out == noErr )
  400.     {
  401.         *handler = theValue.handler ;
  402.         *handlerRefcon = theValue.handlerRefcon ;
  403.     }
  404.  
  405.     return out ;        //<eeh> these hash mgr errors may require translation
  406. }
  407.  
  408.  
  409.  
  410. //———————————————————————— iAEInstallObjectAccessor ————————————————————————}
  411. pascal OSErr
  412. iAEInstallObjectAccessor(DescType            desiredClass ,
  413.                         DescType            containerType ,
  414.                         OSLAccessorUPP        handler ,
  415.                         long                handlerRefcon ,
  416.                         Boolean                isSysHandler)
  417.  
  418. {
  419.     ObjectAccessorKey    key;
  420.     ObjectAccessorValue    theValue;
  421.     GlobalRecHandle        properGlobal;
  422.         
  423.     // NEED TO IMPLEMENT THIS TO CALL THROUGH CONTEXTS
  424.     DebugStr("\pOSLClAcc.iAEInstallObjectAccessor: No good. Exit to shell, please.");
  425.  
  426.     // CHECK PASCAL CODE!!!! should "|" below be "||"? I think so.
  427.     // add check for non-nil and non-odd handler
  428.     if ( ( handler == NULL ) || ( (long)handler & 1) )     //if it's nil or odd... (this is stupid) ...fixes LLD-UPG-4 and -5 
  429.     {
  430.         return paramErr ;
  431.     }
  432.  
  433.     if ( isSysHandler )
  434.         properGlobal = GetSysGlobal() ;
  435.     else
  436.         properGlobal = GetGlobalRef() ;
  437.  
  438.     key.firstKey = desiredClass;
  439.     key.secondKey = containerType;
  440.     theValue.handler = handler;
  441.     theValue.handlerRefcon = handlerRefcon;
  442.     
  443.     // <eeh> do I need to translate this error?
  444.     return AEReplaceEntry( (*properGlobal)->accessorHashTable, NULL,
  445.             (KeyPtr)&key, (HEntryPtr)&theValue ) ;
  446. }
  447.     
  448.  
  449. //———————————————————————— iAERemoveObjectAccessor ————————————————————————
  450. pascal OSErr
  451. iAERemoveObjectAccessor(    DescType        desiredClass ,
  452.                             DescType        containerType ,
  453.                             OSLAccessorUPP    handler ,
  454.                             Boolean            isSysHandler)
  455. {
  456.     ObjectAccessorKey    key ;
  457.     ObjectAccessorValue    theValue ;
  458.     GlobalRecHandle        properGlobal ;
  459.     OSErr                out ;
  460.         
  461.     // NEED TO IMPLEMENT THIS TO CALL THROUGH CONTEXTS
  462.     DebugStr("\pOSLClAcc.iAERemoveObjectAccessor: No good. Exit to shell, please.");
  463.  
  464.     out = noErr;
  465.  
  466.     if ( isSysHandler )
  467.         properGlobal = GetSysGlobal() ;
  468.     else
  469.         properGlobal = GetGlobalRef() ;
  470.  
  471.     key.firstKey = desiredClass ;
  472.     key.secondKey = containerType ;
  473.     
  474.     out = AEGetKeyValue( (*properGlobal)->accessorHashTable,
  475.             NULL, (KeyPtr)&key, (HEntryPtr)&theValue ) ;
  476.  
  477.     // was checking both in same IF, and returning noErr though refusing 
  478.     // to install if the ptrs didn't match. 2/3 
  479.  
  480.     if ( out == noErr )            // added 3/10
  481.     {
  482.         if ( (handler != nil) && (handler != theValue.handler) )                        // fixes LLD-UPG-7 
  483.             out = errAEAccessorNotFound    ;    // changed from handlerNotFound as per LLD??? (comment) 
  484.         else // IF out = NoErr THEN
  485.             out = AERemoveKeyEntry( (*properGlobal)->accessorHashTable,
  486.                 NULL, (KeyPtr)&key) ;
  487.     }
  488.     return out ;        // <eeh> these hash mgr errors may require translation 
  489. }
  490.                                 
  491.